from dataclasses import dataclass
from datetime import datetime
from enum import IntEnum
from time import time,sleep
import os
from traceback import print_exc
import wx
import sys
from collections import OrderedDict, UserList
from . import _insc
from wxPopupError import popuperror
import xlwings as xw
from htmltool import htmlDiffA2lTab, htmltabrowfakelist, htmlparag, htmllist, htmltabrow, htmlparInformTab,DiffType,DiffA2lData
from pathlib import Path
import re
import win32com.client
from bs4 import BeautifulSoup
from xlwings.constants import BordersIndex
from docxcompose.composer import Composer
from docx import Document
from shutil import copy
from tempfile import TemporaryDirectory
from subprocess import check_output

class MyExcel:
    def __init__(self, fpath:Path) -> None:
        if len(xw.apps) > 0:
            self.app = xw.apps[xw.apps.keys()[0]]
            self._newApp = False
        else:
            self.app = xw.App(visible=False, add_book=False)
            self._newApp = True
        self.fpath = fpath
        if fpath.exists():
            self.book = self.app.books.open(fpath)
            self._newFile = False
        else:
            self.book = self.app.books.add()
            self._newFile = True
        self.sheet = (
            self.book.sheets.add("TableSheet")
            if len(self.book.sheets) == 0
            else self.book.sheets[0]
        )
        self.row = 0
        self.buff = []
        self._del_cell = []
        self._buff_start = 0
        self._merge = []
        self._border = []
        self._tabth = []

    def addrow(self, a, has_linethrough = None):
        self.buff.append(a)
        if has_linethrough is None:
            self._del_cell.append([False]*len(a))
        else:
            self._del_cell.append(has_linethrough)
        self.row += 1

    def flush(self):
        maxlen = max(len(x) for x in self.buff)
        for l in self.buff:
            if len(l) < maxlen:
                l.extend([""] * (maxlen - len(l)))
        self.sheet[self._buff_start, 0].value = self.buff
        self.buff = []

        for i,l in enumerate(self._del_cell):
            for j,isdel in enumerate(l):
                if isdel:
                    rg=self.sheet[self._buff_start + i, j]
                    rg.api.Interior.Color = int('#FC0000FF'[1:], 16)
        self._del_cell = []

        for arg in self._border:
            rg=self.sheet.range(*arg)
            rg.api.Borders(BordersIndex.xlEdgeLeft).Weight = 2
            rg.api.Borders(BordersIndex.xlEdgeRight).Weight = 2
            rg.api.Borders(BordersIndex.xlEdgeTop).Weight = 2
            rg.api.Borders(BordersIndex.xlEdgeBottom).Weight = 2
            rg.api.Borders(BordersIndex.xlInsideHorizontal).Weight = 2
            rg.api.Borders(BordersIndex.xlInsideVertical).Weight = 2
        self._border = []

        for arg in self._tabth:
            rg=self.sheet.range(*arg)
            rg.api.Interior.Color = int('#5FFF5FFF'[1:], 16)

        for arg in self._merge:
            self.sheet.range(*arg).merge()
        self._merge = []
        self._buff_start = self.row

    def del_nullrow(self):
        delrow = []
        for i in range(self.row):
            row = self.sheet[i,:]
            for x in row.value:
                if x:
                    isnull = False
                    break
            else:
                isnull = True
            if isnull:
                delrow.append(i)
        for i in reversed(delrow):
            self.sheet[i,:].delete()

    def tabstart(self):
        self._tabstart = self.row

    def tabend(self,width):
        self._border.append(((self.row, 1), (self._tabstart + 1, width)))
        self._tabth.append(((self._tabstart + 1, 1), (self._tabstart + 1, width)))

    def merge_vertical(self,col_idx,length):
        self._merge.append(((self.row+1,col_idx+1),(self.row+1+length,col_idx+1)))

    def merge_transverse(self,col_idx,length):
        self._merge.append(((self.row+1,col_idx+1),(self.row+1,col_idx+1+length)))

    def __del__(self):
        if self._newFile:
            self.book.save(self.fpath)
        else:
            self.book.save()
        if self._newApp:
            self.app.quit()


class DocMerge:
    def __init__(self) -> None:
        self.base_comp = None

    def merge_files(self, file_list:list[Path]):
        for file_path in file_list:
            doc = Document(str(file_path))
            if self.base_comp is None:
                self.base_comp = Composer(doc)
            else:
                self.base_comp.append(doc)

    def save(self, filepath):
        if self.base_comp is not None:
            self.base_comp.save(filepath)
            print('merge docx to:', filepath)


class CheckFile:
    def __init__(self) -> None:
        self.old_file = ['','']
        self.new_file = ['','']
        self.a2l = [None,None]
        self.a2l_name = ['','']
        self.inca_fd_name = ''
        self.filedata:CheckFile.FileData = None

    @dataclass
    class FileData:
        badfile:list[str]
        rgxname:list[str]
        notrgxname:list[str]
        missfile:list[str]
        missauthor:dict[str:list]
        foundfile:list[str]

    @popuperror
    def merge_doc(self):
        if not self.filedata:
            return
        print('merge docx ...')
        with TemporaryDirectory() as dir:
            far_files = []
            for file in [fp for _,_,_,fp in self.filedata.foundfile]:
                far_file = Path(dir) / Path(file).name
                copy(src=file, dst=far_file)
                far_files.append(far_file)
            check_output('git init',cwd=dir)
            check_output('git add .',cwd=dir)
            check_output('git commit -m "a"',cwd=dir)
            for far_file in far_files:
                print('*',far_file)
                os.remove(far_file)
            check_output('git checkout master -f',cwd=dir)
            merge = DocMerge()
            merge.merge_files(far_files)
            merge.save(str(self.otdir / "abcd.docx"))
            # with open('a.txt','w') as f:
            #     def mm(piece,con):
            #         merge = DocMerge()
            #         for x in con:
            #             a=len(far_files)*x//piece
            #             b=len(far_files)*(x+1)//piece
            #             if x+1==piece:b=None
            #             print(far_files[a:b])
            #             f.write(f'## {x}:{a}:{b}\n')
            #             f.write(f'{far_files[a:b]}\n')
            #             merge.merge_files(far_files[a:b])
            #             merge.save(str(self.otdir / f"abcd_{x}_all.docx"))
            #             print()
            #             print()
            #             print()
            #     mm(1,[0])
        print('merge docx done')

    @popuperror
    def check(self, text_1, text_2):
        print('waiting ...')
        xl = MyExcel(Path(text_1))
        names_and_authors=xl.book.sheets[0].used_range[:,0:2].value
        del xl

        file_names = [(Path(x).name, Path(text_2)/x) for x in os.listdir(text_2) if x.endswith(('.doc','.docx'))]

        data = CheckFile.FileData([],[],[],[],{},[])

        l=[]
        for fn,fp in file_names:
            if fn.endswith('.doc'):
                data.badfile.append(fn)
            else:
                l.append((fn,fp))
        file_names = l

        pat=re.compile(r'[\s"]*(?P<rgxid>(RGX|DGX|RBX)_?202[0-9][_-]\d+)')
        for name,author in names_and_authors:
            name = str(name)
            m=re.match(pat,name)
            if m:
                rgxid=m.group('rgxid')
                data.rgxname.append((rgxid,name))
                for fn, fp in file_names:
                    if re.match(rf"{rgxid}[^\d]", fn):
                        data.foundfile.append((name,author,fn,fp))
                        break
                else:
                    data.missfile.append(name)
                    if author not in data.missauthor:
                        data.missauthor[author] = []
                    data.missauthor[author].append(name)
            else:
                data.notrgxname.append(name)

        word = win32com.client.Dispatch("Word.Application")
        word.Visible = False  # 隐藏Word界面
        htmlpaths = {}
        otdir=Path(text_1).parent/'ABCD'
        if not otdir.exists():
            os.mkdir(str(otdir))
        for name, author, fn, fp in data.foundfile:
            html_file = (otdir/fp.name).with_suffix('.html')
            print('$$ to html:', html_file)
            htmlpath = self.to_html(word, fp, html_file)
            htmlpaths[name] = htmlpath
            # htmlpaths[name] = html_file
        word.Quit()

        xl = MyExcel(otdir/'abcd.xlsx')
        xl.sheet.clear()
        foundfilename = set(name for name, author, fn, fp in data.foundfile)
        for name,author in names_and_authors:
            print('$$ html tables to excel:', name)
            if name in foundfilename:
                if not htmlpaths[name]:
                    xl.addrow(['## !! can not read from docx ##', name])
                    continue
                xl.addrow(['## found tables : ##', name])
                self.html_gettable(xl,htmlpaths[name])
            else:
                xl.addrow(['## !! file not found ##', name])
        xl.flush()
        xl.sheet.autofit()
        xl.del_nullrow()
        self.filedata = data
        self.otdir = otdir
        print('almost ...')
        return self.getcompareA2lHtml(data, [])

    def diff_a2l(self, order: list[str], dataonly=False):
        # if a2l[0] is None or a2l[1] is None or self.ins is None or self.incadb is None:
        print('connect INCA ...')
        old, new = self.old_file, self.new_file
        for a2l_path, s19_path in [old, new]:
            assert Path(a2l_path).is_file(), f'文件不存在: "{a2l_path}"'
            assert Path(s19_path).is_file(), f'文件不存在: "{s19_path}"'
        ins = _insc.IncaControl()
        ins.init(expinit = False)
        incadb = ins.inca.GetCurrentDataBase()
        assert incadb, '无法连接到 INCA数据库 '

        if not self.inca_fd_name or not self.a2l_name[0] or not self.a2l_name[1]:
            self.inca_fd_name = f'SH_{datetime.today().strftime("%Y%m%d_%H%M")}_{hash(time())>>13}'
            fd = incadb.AddFolder(self.inca_fd_name)
            for index, (a2l_path, s19_path) in enumerate([old, new]):
                a2l_path = Path(a2l_path).absolute()
                s19_path = Path(s19_path).absolute()
                print(f'INCA read a2l: "{a2l_path}" "{s19_path}"...')
                item = fd.ReadASAP2FileAndHexFile(a2l_path, s19_path)
                self.a2l_name[index] = item.GetName()
                self.a2l[index] = item.Asap2Module()
        else:
            for index in range(2):
                print(f'INCA read a2l: "{self.inca_fd_name}/{self.a2l_name[index]}" ...')
                self.a2l[index] = incadb.BrowseItemInFolder(self.a2l_name[index], self.inca_fd_name)[0].Asap2Module()

        diffparam = []
        print('analyse variable ...')
        for i,name in enumerate(order):
            print('...',name)
            m0, m1, c0, c1, a0, a1 = (
                self.a2l[0].GetMeasurementNamed(name),
                self.a2l[1].GetMeasurementNamed(name),
                self.a2l[0].GetCharacteristicNamed(name),
                self.a2l[1].GetCharacteristicNamed(name),
                self.a2l[0].GetAxisPointNamed(name),
                self.a2l[1].GetAxisPointNamed(name),
            )
            at0 = m0 or c0 or a0
            at1 = m1 or c1 or a1
            if at0 and not at1:
                color = '#E28383FF'
                diffparam.append(DiffA2lData(name=name, type=DiffType.DELETE, inform=(), color=color))
            elif not at0 and at1:
                temp = ins.geta2ldata(at1)
                color = '#B4EEB4' if i % 2 == 0 else '#5CBE61FF'
                diffparam.append(DiffA2lData(name=name, type=DiffType.ADD, inform=temp, color=color))
            elif at0 and at1:
                temp0 = ins.geta2ldata(at0)
                temp = ins.geta2ldata(at1)
                if temp0[:4] == temp[:4] and temp0[5:] == temp[5:]:
                    color = '#FFFFFFFF'
                    diffparam.append(DiffA2lData(name=name, type=DiffType.NOCHANGE, inform=temp, color=color))
                else:
                    color = '#91B7F0FF'
                    diffparam.append(DiffA2lData(name=name, type=DiffType.MODIFY, inform=temp, color=color))
            else:
                color = '#A0A0A0FF'
                diffparam.append(DiffA2lData(name=name, type=DiffType.NOFOUND, inform=(), color=color))
        if dataonly:
            return diffparam
        return self.getDiffA2lHtml(diffparam)

    def getDiffA2lHtml(self, data:list[DiffA2lData]):
        parag = OrderedDict()
        informstr = htmlDiffA2lTab(data)
        parag['newinform'] = informstr
        return HTML_CompareA2l_Main.format(body=''.join(parag.values()), h2style='{background-color:#B0E0E6;\npadding:8px;}\n')

    def html_gettable(self, xl:MyExcel, htmlfile:Path,encoding='GBK'):
        with htmlfile.open(encoding=encoding) as f:
            text = f.read()
        soup=BeautifulSoup(text)
        tabs=soup.find_all('table')
        for tab_idx, tab in enumerate(tabs, 1):
            xl.addrow([f"## @表格{tab_idx} ##"])
            xl.tabstart()
            width=1
            rowspan = []
            for row in tab.find_all('tr'):
                tds = row.find_all(['th','td'])
                l_tdstr = ['\n'.join([p.get_text(strip=True) for p in td.find_all('p')]) for td in tds]
                l_tdhas_linethrough = [bool(td.find('s')) for td in tds]
                l_tmpspan_row = [int(td.attrs.get('rowspan',0)) for td in tds]
                l_tmpspan_col = [int(td.attrs.get('colspan',0)) for td in tds]
                for i,span in enumerate(rowspan):
                    if span > 0:
                        l_tdstr.insert(i,'')
                        l_tdhas_linethrough.insert(i, False)
                        l_tmpspan_row.insert(i,0)
                        l_tmpspan_col.insert(i,0)
                for i,span in enumerate(l_tmpspan_col):
                    if span > 1:
                        l_tdstr = l_tdstr[: i + 1] + [""] * (span - 1) + l_tdstr[i + 1 :]
                        l_tdhas_linethrough = l_tdhas_linethrough[: i + 1] + [l_tdhas_linethrough[i]] * (span - 1) + l_tdhas_linethrough[i + 1 :]
                        xl.merge_transverse(i, span - 1)
                if len(rowspan) < len(l_tmpspan_row):
                    rowspan.extend([0] * (len(l_tmpspan_row) - len(rowspan)))
                for i, span in enumerate(l_tmpspan_row):
                    if span>1:
                        xl.merge_vertical(i,span-1)
                    rowspan[i] = rowspan[i] + span - 1
                    if rowspan[i] < 0:
                        rowspan[i] = 0
                if l_tdstr:
                    xl.addrow(l_tdstr, l_tdhas_linethrough)
                    width = len(l_tdstr) if len(l_tdstr) > width else width
            xl.tabend(width)

    def to_html(self, word, file: Path, html_file: Path) -> Path:
        # print('$$',file)
        doc = word.Documents.Open(str(file))
        try:
            doc.SaveAs(str(html_file), FileFormat=8)
        except:
            print_exc()
            html_file = ''
        finally:
            try:
                doc.Close(SaveChanges=0)
            except:
                # assert False, f'"{file}"出错无法被正常关闭'
                print(f'"{file}"出错无法被正常关闭')
        return html_file

    def getcompareA2lHtml(self, data:FileData, order:list[str]):
        parag = OrderedDict()
        parag['badfile'] = HTML_CommParag.format(head='无法识别".doc"结尾的文档或文档出错',con=htmllist(data.badfile))
        parag['notrgxname'] = HTML_CommParag.format(head='excel里不知道是什么RGX',con=htmllist([f'"{x}"' for x in data.notrgxname]))
        parag['missfile'] = HTML_CommParag.format(head='在文件夹里没找到的RGX',con=htmllist([f'"{x}"' for x in data.missfile]))
        parag['missauthor'] = HTML_CheckFile_MissAuthor(data.missauthor)
        parag['foundfile'] = HTML_CommParag.format(head='找到的RGX',con=htmllist([f'"{fn}"' for _,_,fn,_ in data.foundfile]))
        return HTML_CompareA2l_Main.format(body=''.join(parag.values()), h2style='{background-color:#B0E0E6;\npadding:8px;}\n')


class CheckFileWin(wx.Frame):
    """检查文件"""

    def __init__(self, parent, mainobj):
        wx.Frame.__init__(self, parent=parent, title='检查文件',
                          size=(700, 700), style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT)
        self.mainobj = mainobj
        self.SetBackgroundColour(wx.Colour(200, 210, 210))

        self.pl = wx.Panel(self, size=(700, 700))
        self.text_1 = wx.TextCtrl(self.pl)
        self.text_2 = wx.TextCtrl(self.pl)
        self.text_old = wx.TextCtrl(self.pl)
        self.text_new = wx.TextCtrl(self.pl)
        self.text_log = wx.TextCtrl(self.pl, style=wx.TE_MULTILINE | wx.TE_READONLY, size=(80, 80))
        self.bt_check = wx.Button(self.pl, label='检查文件', size=(100, 40))
        self.bt_diff = wx.Button(self.pl, label='变量核对', size=(100, 40))
        self.bt_merge = wx.Button(self.pl, label='合并RGX文档', size=(100, 40))
        self.bt_a = wx.Button(self.pl, label='需求名称excel', size=(120, 40))
        self.bt_b = wx.Button(self.pl, label='存放docx的文件夹', size=(120, 40))
        self.bt_old = wx.Button(self.pl, label='老的a2l和s19', size=(120, 40))
        self.bt_new = wx.Button(self.pl, label='新的a2l和s19', size=(120, 40))

        self.sizer = wx.GridBagSizer(5, 10)
        self.sizer.Add(self.bt_a, pos=(0, 0), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(self.text_1, pos=(0, 1), span=(1, 1), flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
        self.sizer.Add(10, 10, pos=(1, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt_b, pos=(2, 0), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(self.text_2, pos=(2, 1), span=(1, 1), flag=wx.EXPAND | wx.RIGHT, border=10)
        self.sizer.Add(10, 10, pos=(3, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt_check, pos=(4, 0), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(self.bt_merge, pos=(4, 1), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(10, 10, pos=(5, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt_old, pos=(6, 0), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(self.text_old, pos=(6, 1), span=(1, 1), flag=wx.EXPAND | wx.RIGHT, border=10)
        self.sizer.Add(10, 10, pos=(7, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt_new, pos=(8, 0), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(self.text_new, pos=(8, 1), span=(1, 1), flag=wx.EXPAND | wx.RIGHT, border=10)
        self.sizer.Add(10, 10, pos=(10, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt_diff, pos=(11, 1), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(10, 10, pos=(12, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.text_log, pos=(13, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL, border=5)

        self.sizer.AddGrowableCol(1)
        self.sizer.AddGrowableRow(13)
        self.pl.SetSizer(self.sizer)
        self.Bind(wx.EVT_BUTTON, self.on_button_check, self.bt_check)
        self.Bind(wx.EVT_BUTTON, self.on_button_diff, self.bt_diff)
        self.Bind(wx.EVT_BUTTON, self.on_button_merge, self.bt_merge)
        self.Bind(wx.EVT_BUTTON, self.on_button_a, self.bt_a)
        self.Bind(wx.EVT_BUTTON, self.on_button_b, self.bt_b)
        self.Bind(wx.EVT_BUTTON, self.on_button_old, self.bt_old)
        self.Bind(wx.EVT_BUTTON, self.on_button_new, self.bt_new)

        self.mainobj.checkfile = CheckFile()

        self.bt_merge.Disable()
        self.Centre()
        self.Show()

    def on_button_check(self, event):
        self.mainobj.set_stdout(self.text_log)
        text_1 = self.text_1.GetValue().strip()
        text_2 = self.text_2.GetValue().strip()
        if not text_1 or not text_2:
            return
        self.bt_check.Disable()
        myhtml = self.mainobj.checkfile.check(text_1, text_2)
        wx.CallAfter(self.mainobj.gui.showhtml, myhtml)
        print('done ...')
        self.bt_merge.Enable()
        self.bt_check.Enable()
        self.mainobj.unset_stdout(self.text_log)
        
    def on_button_diff(self, event):
        self.mainobj.set_stdout(self.text_log)
        text_old = self.text_old.GetValue().strip()
        text_new = self.text_new.GetValue().strip()
        if ';' in text_old and ';' in text_new:
            self.mainobj.checkfile.old_file = text_old.split(';')
            self.mainobj.checkfile.new_file = text_new.split(';')
            self.checkvarwin = CheckVarWin(parent=self,mainobj=self.mainobj)
        self.mainobj.unset_stdout(self.text_log)

    def on_button_merge(self, event):
        self.mainobj.set_stdout(self.text_log)
        self.bt_merge.Disable()
        self.mainobj.checkfile.merge_doc()
        self.bt_merge.Enable()
        self.mainobj.unset_stdout(self.text_log)

    def on_button_a(self, event):
        self.bt_a.Disable()
        with wx.FileDialog(None, '选择excel', style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fd:
            if not fd.ShowModal() == wx.ID_CANCEL:
                path = fd.GetPath()
                self.text_1.SetValue(path)
        self.bt_a.Enable()

    def on_button_b(self, event):
        self.bt_b.Disable()
        with wx.DirDialog(None, '存放docx的文件夹') as fd:
            if not fd.ShowModal() == wx.ID_CANCEL:
                path = fd.GetPath()
                self.text_2.SetValue(path)
        self.bt_b.Enable()

    def on_button_old(self, event):
        self.bt_old.Disable()
        path_1, path_2 = "", ""
        with wx.FileDialog(None, '选择A2L', style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fd:
            if not fd.ShowModal() == wx.ID_CANCEL:
                path_1 = fd.GetPath()
        with wx.FileDialog(None, '选择S19', style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fd:
            if not fd.ShowModal() == wx.ID_CANCEL:
                path_2 = fd.GetPath()
        if path_1 and path_2:
            self.text_old.SetValue(f"{path_1};{path_2}")
        self.bt_old.Enable()

    def on_button_new(self, event):
        self.bt_new.Disable()
        path_1, path_2 = "", ""
        with wx.FileDialog(None, '选择A2L', style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fd:
            if not fd.ShowModal() == wx.ID_CANCEL:
                path_1 = fd.GetPath()
        with wx.FileDialog(None, '选择S19', style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fd:
            if not fd.ShowModal() == wx.ID_CANCEL:
                path_2 = fd.GetPath()
        if path_1 and path_2:
            self.text_new.SetValue(f"{path_1};{path_2}")
        self.bt_new.Enable()


class CheckVarWin(wx.Frame):
    """检查数据"""

    def __init__(self, parent, mainobj):
        wx.Frame.__init__(self, parent=parent, title='检查数据',
                          size=(700, 500), style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT)
        self.mainobj = mainobj
        self.SetBackgroundColour(wx.Colour(200, 210, 210))

        self.pl = wx.Panel(self, size=(700, 500))
        self.text = wx.TextCtrl(self.pl, style=wx.TE_MULTILINE)
        self.text_log = wx.TextCtrl(self.pl, style=wx.TE_MULTILINE | wx.TE_READONLY, size=(80, 80))
        self.bt = wx.Button(self.pl, label='检查', size=(100, 40))

        self.sizer = wx.GridBagSizer(5, 10)
        self.sizer.Add(self.text, pos=(0, 1), span=(1, 1), flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
        self.sizer.Add(10, 10, pos=(1, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt, pos=(2, 1), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(10, 10, pos=(3, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.text_log, pos=(4, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL, border=5)

        self.sizer.AddGrowableCol(1)
        self.sizer.AddGrowableRow(0)
        self.pl.SetSizer(self.sizer)
        self.Bind(wx.EVT_BUTTON, self.on_button, self.bt)

        self.Centre()
        self.Show()

    @popuperror
    def on_button(self, event):
        text = self.text.GetValue().strip()
        if not text:
            return
        self.bt.Disable()
        self.mainobj.set_stdout(self.text_log)
        l = [x.strip() for x in text.split() if x.strip()]
        myhtml = self.mainobj.checkfile.diff_a2l(l)
        wx.CallAfter(self.mainobj.gui.showhtml, myhtml)
        self.bt.Enable()
        self.mainobj.unset_stdout(self.text_log)

########################################## HTML ####################################################

HTML_CompareA2l_Main = """<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="author" content="XiePeng">
<title>A2L比对信息</title>
<style type="text/css">
h2 {h2style}
</style>
</head>
<body>
{body}
</body>
</html>
"""

HTML_CompareA2l_Overview = """
<p>
<h2>总览</h2>
<ul>
<li><b>新A2L</b>: {a2l0}<br/>{a2l0_path}</li>
<li><b>旧A2L</b>: {a2l1}<br/>{a2l1_path}</li>
<li><b>新增变量</b>: {newnum} 个</li>
<li><b>删除变量</b>: {delnum} 个</li>
<li color="#DC143C"><b>新A2L出错的变量</b>: <strong>{errnum0}</strong> 个</li>
<li><b>索引</b></li>
    <ul>
    <li><a href="#newparams">新增变量</a></li>
    <li><a href="#delparams">删除变量</a></li>
    <li><a href="#newinform">新增变量信息</a></li>
    <li><a href="#error">错误变量</a></li>
    </ul>
</ul>
</p>
"""
HTML_CommParag = """
<p>
<h2>{head}</h2>
<dl>
<dt></dt>
    <dd>
    {con}
    </dd>
</dl>
</p>
"""
def HTML_CheckFile_MissAuthor(dic:dict):
    s=''
    for k,v in dic.items():
        s+=f'<tr><td>{k}</td>'
        s+=f'<td>'
        s+=htmllist(v)
        s+=f'</td>'
        s+=f'</tr>\n'
    return f"""
<p>
<h2>在文件夹里没找到的RGX</h2>
<table border="1" cellpadding="4" cellspacing="0">
<tr>
    <th>作者</th>
    <th>缺失RGX</th>
</tr>
{s}
</table>
</p>
"""
HTML_CompareA2l_Newparams = """
<p>
<h2><a name="newparams">新增变量</a></h2>
<dl>
<dt></dt>
    <dd>
    {0}
    </dd>
</dl>
</p>
"""
HTML_CompareA2l_Delparams = """
<p>
<h2><a name="delparams">删除变量</a></h2>
<dl>
<dt></dt>
    <dd>
    {0}
    </dd>
</dl>
</p>
"""
HTML_CompareA2l_Newinform = """
<p>
<h2><a name="newinform">新增变量信息</a></h2>
<dl>
<dt></dt>
    <dd>
    {0}
    </dd>
</dl>
</p>
"""
HTML_CompareA2l_Error = """
<p>
<h2><a name="error">错误变量</a></h2>
{0}
</p>
"""
